/*******************************************************************************
 * Copyright (c) 2002 Boris Pruessmann and others. All rights reserved. This
 * program and the accompanying materials are made available under the terms of
 * the Common Public License v0.5 which accompanies this distribution, and is
 * available at http://www.eclipse.org/legal/cpl-v05.html
 * 
 * Contributors: Boris Pruessmann - Initial implementation
 ******************************************************************************/
package net.sourceforge.perforce.ui;

import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;

import net.sourceforge.perforce.core.ISubmitValidator;
import net.sourceforge.perforce.core.PerforceException;
import net.sourceforge.perforce.core.api.IPerforceServer;
import net.sourceforge.perforce.core.internal.api.ChangeSpec;

import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.IWorkspaceRoot;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.core.runtime.Status;
import org.eclipse.jface.dialogs.Dialog;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.preference.IPreferenceStore;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.widgets.Display;
import org.eclipse.ui.IEditorPart;
import org.eclipse.ui.IWorkbenchPage;
import org.eclipse.ui.IWorkbenchWindow;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.internal.WorkbenchPage;

/**
 * @version $Revision: 488 $
 * @author <a href="mailto:bpruessmann@users.sourceforge.net">Boris
 *         Pruessmann</a>
 */
public class UnsavedResourcesSubmitValidator implements ISubmitValidator {
  //----------------------------------------------------------------------------
  // -- Public Methods

  /** @see ISubmitValidator#validateChangeSpec(IPerforceServer, ChangeSpec) */
  public IStatus validateChangeSpec(IPerforceServer server, ChangeSpec changeSpec) {
    IPreferenceStore store = PerforceUIPlugin.getPlugin().getPreferenceStore();
    String behavior = store.getString(IPerforceUIConstants.PREF_UNSAVED_RESOURCES_BEHAVIOR);
    if (IPerforceUIConstants.URB_SUBMIT.equals(behavior)) {
      return getOkStatus();
    }

    try {
      IWorkspaceRoot root = PerforceUIPlugin.getWorkspace().getRoot();
      Set<IResource> resources = changeSpec.getResources(server, root);

      Map<IResource, IEditorPart> unsavedResources = getUnsavedResources(server, resources);
      if (!unsavedResources.isEmpty()) {
        if (IPerforceUIConstants.URB_PROMPT.equals(behavior)) {
          final String message =
              "The changelist you are trying to submit contains "
                  + "files that have with unsaved modifications.";

          final Display display = Display.getDefault();
          final int action[] = {-1};
          display.syncExec(new Runnable() {
            public void run() {
              Image image = Dialog.getImage(Dialog.DLG_IMG_WARNING);
              MessageDialog dlg =
                  new MessageDialog(display.getActiveShell(), "Perforce Team Provider", image,
                      message, MessageDialog.WARNING, new String[] {"Continue", "Save and Submit",
                          "Cancel"}, 2);
              action[0] = dlg.open();

            }
          });
          if (action[0] == 1) {
            behavior = IPerforceUIConstants.URB_AUTOSAVE;
          }
          if (action[0] == 2) {
            return new Status(Status.ERROR, PerforceUIPlugin.ID, 0,
                "Submit has been aborted by the user.", //$NON-NLS-1$
                null);
          }
        }
        if (IPerforceUIConstants.URB_AUTOSAVE.equals(behavior)) {
          for (Iterator<IEditorPart> i = unsavedResources.values().iterator(); i.hasNext();) {
            IEditorPart editor = i.next();
            editor.doSave(new NullProgressMonitor());
          }
        }
      }


      return getOkStatus();
    } catch (PerforceException e) {
      return e.getStatus();
    }
  }

  private Map<IResource, IEditorPart> getUnsavedResources(IPerforceServer server,
      Set<IResource> resources) {
    Map<IResource, IEditorPart> unsavedResourceMap = new HashMap<IResource, IEditorPart>();
    IWorkbenchWindow windows[] = PlatformUI.getWorkbench().getWorkbenchWindows();
    for (int i = 0; i < windows.length; i++) {
      IWorkbenchPage pages[] = windows[i].getPages();
      for (int j = 0; j < pages.length; j++) {
        WorkbenchPage page = (WorkbenchPage) pages[j];
        IEditorPart editors[] = page.getDirtyEditors();
        for (int k = 0; k < editors.length; k++) {
          IEditorPart editor = editors[k];
          if (editor.isDirty()) {
            IResource resource = (IResource) editor.getEditorInput().getAdapter(IResource.class);
            if (resources.contains(resource)) unsavedResourceMap.put(resource, editor);
          }
        }
      }
    }
    return unsavedResourceMap;
  }

  private Status getOkStatus() {
    return new Status(Status.OK, PerforceUIPlugin.ID, 0, "", null); //$NON-NLS-1$
  }
}
